import { Component, ComponentFactoryResolver, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { DomService, FormViewModel, WebCommand, WebCommandMetadata } from '@farris/designer-services';
import { LoadingService } from '@farris/ui-loading';
import { MessagerService } from '@farris/ui-messager';
import { BsModalService } from '@farris/ui-modal';
import { NotifyService } from '@farris/ui-notify';
import { TreeTableColumn, TreeTableComponent } from '@farris/ui-treetable';
import { Subscription } from 'rxjs';
import { ActionsBuilder } from './services/actions-builder';
import { CmdBasicEditorComponent } from './cmd-basic-editor/cmd-basic-editor.component';
import { Command } from './entity/command';
import { WebCmdHandlerManager } from './services/webcmd-handler.manager';
import { CommandSelectorComponent } from './command-selector/command-selector.component';
// import { WebCommand, WebCommandMetadata } from '@gsp-cmp/webcommand';
import { ViewModelListBuilder } from './services/vm-list-builder';
import { ExecuteNode } from './entity/execute-node';


@Component({
    selector: 'app-method-manager',
    templateUrl: './method-manager.component.html',
    styleUrls: ['./method-manager.component.css'],
    providers: [ActionsBuilder, WebCmdHandlerManager]
})
export class MethodManagerComponent implements OnInit, OnDestroy {
    /** 导航条数据源 */
    viewModelTabs = [];

    /** 当前选中的视图模型 */
    activeViewModel: FormViewModel;

    /** 命令订阅 */
    private subscriptions: Subscription[];

    /** 命令列表数据 */
    commandsData: Command[];

    commandsDataColumn: TreeTableColumn[] = [];

    /** 参数列表 */
    paramsData = [];

    /** 按钮是否可用 */
    enableButtons = false;

    /** 选中已失效的命令: 只能删除不能编辑 */
    inValidCommandSelected = false;

    isSelectCommandNode = true;

    /** 当前选中的命令id，用于定位树表行 */
    selectedCommandId: string;

    /** 命令树表实例 */
    @ViewChild('tt') cmdTree: TreeTableComponent;

    /** 当前选中的左侧节点（命令） */
    currentTreeNode: Command | any;


    @ViewChild('methodNameTpl') methodNameTpl: TemplateRef<any>;

    constructor(
        private domService: DomService,
        private actionsBuilder: ActionsBuilder,
        private msgService: MessagerService,
        private notifyService: NotifyService,
        private webCmdHandlerManager: WebCmdHandlerManager,
        private resolver: ComponentFactoryResolver,
        private modalService: BsModalService,
        private injector: Injector,
        private loading: LoadingService) { }

    ngOnInit(): void {
        this.commandsDataColumn = [{ field: 'name', title: '方法名称', template: this.methodNameTpl, showTips: true }, { field: 'code', title: '方法编号', showTips: true }];

        this.subscriptions = [];
        this.subscriptions.push(this.actionsBuilder.subscribe(
            commands => {
                if (typeof (commands) === 'object' && commands.flag === 'error') {
                    this.loading.close();
                    this.msgService.warning(commands.msg);
                    this.enableButtons = false;
                } else {
                    this.refresh(commands);
                    this.enableButtons = true;
                    this.loading.close();
                }

            },
            err => {
                this.loading.close();
                this.msgService.warning(err);
                this.enableButtons = false;
            }));
    }

    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }

    /**
     * 初始模型数据
     */
    refreshVmMethod() {
        const vmBuilder = new ViewModelListBuilder(this.domService);

        const result = vmBuilder.resolveViewModelList();
        if (!result) {
            return;
        }
        this.viewModelTabs = result.viewModelTabs || [];

        // 保留上次选中的模型
        if (this.activeViewModel) {
            const vm = this.viewModelTabs.find(v => v.id === this.activeViewModel.id);
            if (vm) {
                this.activeViewModel = this.domService.module.viewmodels.find(v => v.id === vm.id);
            } else {
                this.activeViewModel = result.activeViewModel;
            }
        } else {
            this.activeViewModel = result.activeViewModel;
        }


        this.loading.show();

        this.currentTreeNode = null;

        window.suspendChangesOnForm = true;

        this.actionsBuilder.build(this.activeViewModel.commands);
    }


    /**
     * 行颜色
     */
    rowCls = (treeNode) => {
        if (treeNode.isInValid) {
            return {
                style: {
                    color: '#a2a2a2'
                }
            };
        }
        return {
            style: {
                color: '#424347'
            }
        };
    }

    /**
     * 切换组件
     * @param viewModelId 视图模型id
     */
    onViewModelChanged(viewModelId: string) {
        window.suspendChangesOnForm = true;
        this.activeViewModel = this.domService.module.viewmodels.find(v => v.id === viewModelId);
        this.loading.show();

        this.selectedCommandId = null;
        this.currentTreeNode = null;

        this.actionsBuilder.build(this.activeViewModel.commands);
    }

    private refresh(data: any[]) {

        this.commandsData = data;

        // 记录选中id，treetable会在加载完成后触发定位
        if (data.length) {
            this.cmdTree.selectValue = this.selectedCommandId ? this.selectedCommandId : this.commandsData[0].data.id;
        } else {
            this.cmdTree.selectValue = null;
        }

        if (this.currentTreeNode && this.currentTreeNode.parent instanceof Command) {
            const commandNode = this.commandsData.find(d => d.id === this.currentTreeNode.parent.id);
            this.currentTreeNode = commandNode && commandNode.children.find(d => d.data.id === this.cmdTree.selectValue);

        } else {
            this.currentTreeNode = this.commandsData.find(d => d.data && d.data.id === this.cmdTree.selectValue);
        }

        this.updateViewModel(data);
        this.refreshParamListData();

        window.suspendChangesOnForm = false;
    }

    /**
     * 更新参数列表
     */
    private refreshParamListData() {
        if (this.commandsData.length === 0) {
            this.paramsData = [];
            return;
        }
        if (this.currentTreeNode instanceof Command) {
            this.paramsData = this.currentTreeNode.params || [];
        } else {
            this.paramsData = [];
        }
    }

    /**
     * 将变更同步到表单DOM中
     * @param commands 命令列表
     */
    private updateViewModel(commands) {
        if (!commands || !this.activeViewModel) {
            return;
        }

        const commandsJson = [];
        if (commands.length > 0) {
            for (const command of commands) {
                if (command instanceof Command && command.toJson) {
                    commandsJson.push(command.toJson());
                } else {
                    commandsJson.push(command.data);
                }
            }
            this.activeViewModel.commands = commandsJson;
        } else {
            this.activeViewModel.commands = [];
        }

    }

    /**
     * 切换选中的命令
     */
    changeSelectedComand(event: any) {
        this.currentTreeNode = event.node;

        this.isSelectCommandNode = !!!event.node.parent;
        this.selectedCommandId = this.currentTreeNode.id;

        // 已失效的命令: 只能删除，不能编辑
        if (event.node.isInValid) {
            this.inValidCommandSelected = true;
            this.paramsData = [];
            return;
        }
        this.inValidCommandSelected = false;

        this.refreshParamListData();
    }

    /**
     * 删除命令
     */
    onDeleteMethod() {
        if (!this.currentTreeNode || !this.isSelectCommandNode) {
            this.notifyService.warning('请先选择方法');
            return;
        }
        this.msgService.question('确定删除方法？', () => {

            // 删除后自动定位到下一条命令
            const index = this.commandsData.findIndex(d => d.id === this.currentTreeNode.id);
            if (index > -1 && index < this.commandsData.length - 1) {
                this.selectedCommandId = this.commandsData[index + 1].data.id;
            } else {
                this.selectedCommandId = null;
            }

            const command = this.currentTreeNode as Command;
            this.currentTreeNode = null;

            this.actionsBuilder.removeCommand(command);
            this.webCmdHandlerManager.removeCommand(command);

            this.paramsData = [];

            this.notifyService.warning('删除方法后请重新绑定控件交互事件！');
        });

    }

    /**
     * 编辑命令名称和编号
     */
    onEditMethod() {
        if (!this.currentTreeNode || !this.isSelectCommandNode) {
            this.notifyService.warning('请先选择方法');
            return;
        }
        if (this.currentTreeNode.isInValid) {
            this.notifyService.warning('方法已失效，不支持编辑');
            return;
        }
        const compFactory = this.resolver.resolveComponentFactory(CmdBasicEditorComponent);
        const compRef = compFactory.create(this.injector);
        const modalConfig = {
            title: '编辑方法',
            width: 450,
            height: 220,
            showMaxButton: false,
            showButtons: true,
            buttons: compRef.instance.modalFooter
        };
        compRef.instance.currentCommand = this.currentTreeNode;
        compRef.instance.commands = this.commandsData;
        compRef.instance.viewModelId = this.activeViewModel.id;

        const modalPanel = this.modalService.show(compRef, modalConfig);
        compRef.instance.closeModal.subscribe(() => {
            modalPanel.close();
        });

        compRef.instance.submitModal.subscribe((data) => {
            if (data) {
                this.cmdTree.loadData(this.commandsData);
                this.updateViewModel(this.commandsData);
                modalPanel.close();
            }
        });
    }

    /**
     * 弹出命令选择器
     */
    onAddMethod() {
        const compFactory = this.resolver.resolveComponentFactory(CommandSelectorComponent);
        const compRef = compFactory.create(this.injector);
        const modalConfig = {
            title: '添加方法',
            width: 600,
            height: 560,
            showMaxButton: true,
            showButtons: true,
            buttons: compRef.instance.modalFooter
        };
        const modalPanel = this.modalService.show(compRef, modalConfig);

        compRef.instance.commandSelected.subscribe((d) => {
            this.commandSelected(d.selectedCommands, d.newCmds);
            modalPanel.close();
        });

        compRef.instance.closeModal.subscribe(() => {
            modalPanel.close();
        });
    }

    /**
     * 添加命令事件
     */
    commandSelected(data: Array<{ cmd: WebCommand, cmp: WebCommandMetadata }>, newCmds: any[]) {
        if (!data || data.length === 0) {
            return;
        }

        // 新增的构件
        const webcmdList = this.domService.getWebCmds();
        newCmds.forEach(newCmd => {
            if (!webcmdList.find(c => c.id === newCmd.id)) {
                webcmdList.push(newCmd);
            }
        });
        // 新增的命令
        data.forEach(d => {
            const command = this.actionsBuilder.addCommand(d.cmd, d.cmp, this.activeViewModel.id);
            this.webCmdHandlerManager.addCommand(command, d.cmd.Code);
        });


    }

    /**
     * 参数编辑器：选择应用时触发
     */
    onApplicationSelectionChange(event: any) {
        const { result: { id = undefined, entrance = undefined } = null, command = null } = event || {};
        if (!command) {
            return;
        }
        if (this.currentTreeNode.params) {
            // 选择应用id后，自动填写应用入口参数
            if (entrance !== undefined) {
                const property = this.currentTreeNode.params.find(item => item.name === 'appEntrance');
                if (property) {
                    property.value = entrance;
                }
            }
            if (id !== undefined) {
                const property = this.currentTreeNode.params.find(item => item.name === 'funcOrAppId');
                if (property) {
                    property.value = id;
                }
            }
        }
        this.updateViewModel(this.commandsData);
    }

    /**
     * 参数编辑器：变更参数值时触发
     * @param currentCommand 当前命令
     * @param currentParam 当前编辑参数
     * @param value 参数值
     */
    getParameterValue() {
        this.updateViewModel(this.commandsData);
    }


    /**
     * 更新当前命令的参数信息---用于构件中参数被移除的场景
     */
    updateCommandParamFromWebCmd() {
        this.currentTreeNode.params = this.currentTreeNode.params.filter(co => !co.isDisused);
        this.currentTreeNode.needRefreshParam = false;


        this.refreshParamListData();

        this.updateViewModel(this.commandsData);

        this.notifyService.success('更新成功');
    }

}
